// -----------------------------
// Author: 		Dhaenens Gert 
// Creation: 	8/28/2013 7:02:25 PM				
// -----------------------------

#ifndef _LuaMethod_h
#define _LuaMethod_h

#include "LuaObject.h"
#include "LuaRef.h"
#include "LuaStackGuard.h"
#include "Lua.h"
#include "LuaStack.h"

namespace ObjectLua
{

	namespace Internal
	{

		/*
		//	Used for binding
		//	a method to Lua
		//	0 Arguments
		//	Used internally
		*/
		template<typename Class, typename R>
		class LuaMethod_0 : public LuaObject
		{
		public:
			typedef R (Class::*Method)();
			typedef LuaMethod_0<Class,R>	Type;

			LuaMethod_0(Lua* lpLua, Method lpMethod) : LuaObject(lpLua) , m_lpMethod(lpMethod) {}
			~LuaMethod_0() {}

			/*
			//	Used to actually bind
			//	the Method to Lua
			*/
			static void bind(Lua* lpLua, LuaTable* lpTable, const char* name, Method lpMethod);
			/*
			//	Callback for Lua
			*/
			static int	callback(lua_State* lpLuaState);
			/*
			//	Call the Method
			*/
			int	call() const;

		private:
			Method	m_lpMethod;
		};



		/*
		//	Used for binding
		//	a method to Lua
		//	1 Arguments
		//	Used internally
		*/
		template<typename Class, typename R, typename P0>
		class LuaMethod_1 : public LuaObject
		{
		public:
			typedef R (Class::*Method)(P0);
			typedef LuaMethod_1<Class,R,P0>	Type;

			LuaMethod_1(Lua* lpLua, Method lpMethod) : LuaObject(lpLua) , m_lpMethod(lpMethod) {}
			~LuaMethod_1() {}

			/*
			//	Used to actually bind
			//	the Method to Lua
			*/
			static void bind(Lua* lpLua, LuaTable* lpTable, const char* name, Method lpMethod);
			/*
			//	Callback for Lua
			*/
			static int	callback(lua_State* lpLuaState);
			/*
			//	Call the Method
			*/
			int	call() const;

		private:
			Method	m_lpMethod;
		};



		/*
		//	Used for binding
		//	a method to Lua
		//	2 Arguments
		//	Used internally
		*/
		template<typename Class, typename R, typename P0, typename P1>
		class LuaMethod_2 : public LuaObject
		{
		public:
			typedef R (Class::*Method)(P0,P1);
			typedef LuaMethod_2<Class,R,P0,P1>	Type;

			LuaMethod_2(Lua* lpLua, Method lpMethod) : LuaObject(lpLua) , m_lpMethod(lpMethod) {}
			~LuaMethod_2() {}

			/*
			//	Used to actually bind
			//	the Method to Lua
			*/
			static void bind(Lua* lpLua, LuaTable* lpTable, const char* name, Method lpMethod);
			/*
			//	Callback for Lua
			*/
			static int	callback(lua_State* lpLuaState);
			/*
			//	Call the Method
			*/
			int	call() const;

		private:
			Method	m_lpMethod;
		};
		


		/*
		//	Used for binding
		//	a method to Lua
		//	3 Arguments
		//	Used internally
		*/
		template<typename Class, typename R, typename P0, typename P1, typename P2>
		class LuaMethod_3 : public LuaObject
		{
		public:
			typedef R (Class::*Method)(P0,P1,P2);
			typedef LuaMethod_3<Class,R,P0,P1,P2>	Type;

			LuaMethod_3(Lua* lpLua, Method lpMethod) : LuaObject(lpLua) , m_lpMethod(lpMethod) {}
			~LuaMethod_3() {}

			/*
			//	Used to actually bind
			//	the Method to Lua
			*/
			static void bind(Lua* lpLua, LuaTable* lpTable, const char* name, Method lpMethod);
			/*
			//	Callback for Lua
			*/
			static int	callback(lua_State* lpLuaState);
			/*
			//	Call the Method
			*/
			int	call() const;

		private:
			Method	m_lpMethod;
		};



		/*
		//	Used for binding
		//	a method to Lua
		//	4 Arguments
		//	Used internally
		*/
		template<typename Class, typename R, typename P0, typename P1, typename P2, typename P3>
		class LuaMethod_4 : public LuaObject
		{
		public:
			typedef R (Class::*Method)(P0,P1,P2,P3);
			typedef LuaMethod_4<Class,R,P0,P1,P2,P3>	Type;

			LuaMethod_4(Lua* lpLua, Method lpMethod) : LuaObject(lpLua) , m_lpMethod(lpMethod) {}
			~LuaMethod_4() {}

			/*
			//	Used to actually bind
			//	the Method to Lua
			*/
			static void bind(Lua* lpLua, LuaTable* lpTable, const char* name, Method lpMethod);
			/*
			//	Callback for Lua
			*/
			static int	callback(lua_State* lpLuaState);
			/*
			//	Call the Method
			*/
			int	call() const;

		private:
			Method	m_lpMethod;
		};



		/*
		//	Used for binding
		//	a method to Lua
		//	5 Arguments
		//	Used internally
		*/
		template<typename Class, typename R, typename P0, typename P1, typename P2, typename P3, typename P4>
		class LuaMethod_5 : public LuaObject
		{
		public:
			typedef R (Class::*Method)(P0,P1,P2,P3,P4);
			typedef LuaMethod_5<Class,R,P0,P1,P2,P3,P4>	Type;

			LuaMethod_5(Lua* lpLua, Method lpMethod) : LuaObject(lpLua) , m_lpMethod(lpMethod) {}
			~LuaMethod_5() {}

			/*
			//	Used to actually bind
			//	the Method to Lua
			*/
			static void bind(Lua* lpLua, LuaTable* lpTable, const char* name, Method lpMethod);
			/*
			//	Callback for Lua
			*/
			static int	callback(lua_State* lpLuaState);
			/*
			//	Call the Method
			*/
			int	call() const;

		private:
			Method	m_lpMethod;
		};



		/*
		//	Used for binding
		//	a method to Lua
		//	6 Arguments
		//	Used internally
		*/
		template<typename Class, typename R, typename P0, typename P1, typename P2, typename P3, typename P4, typename P5>
		class LuaMethod_6 : public LuaObject
		{
		public:
			typedef R (Class::*Method)(P0,P1,P2,P3,P4,P5);
			typedef LuaMethod_6<Class,R,P0,P1,P2,P3,P4,P5>	Type;

			LuaMethod_6(Lua* lpLua, Method lpMethod) : LuaObject(lpLua) , m_lpMethod(lpMethod) {}
			~LuaMethod_6() {}

			/*
			//	Used to actually bind
			//	the Method to Lua
			*/
			static void bind(Lua* lpLua, LuaTable* lpTable, const char* name, Method lpMethod);
			/*
			//	Callback for Lua
			*/
			static int	callback(lua_State* lpLuaState);
			/*
			//	Call the Method
			*/
			int	call() const;

		private:
			Method	m_lpMethod;
		};



		/*
		//	Used for binding
		//	a method to Lua
		//	7 Arguments
		//	Used internally
		*/
		template<typename Class, typename R, typename P0, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6>
		class LuaMethod_7 : public LuaObject
		{
		public:
			typedef R (Class::*Method)(P0,P1,P2,P3,P4,P5,P6);
			typedef LuaMethod_7<Class,R,P0,P1,P2,P3,P4,P5,P6>	Type;

			LuaMethod_7(Lua* lpLua, Method lpMethod) : LuaObject(lpLua) , m_lpMethod(lpMethod) {}
			~LuaMethod_7() {}

			/*
			//	Used to actually bind
			//	the Method to Lua
			*/
			static void bind(Lua* lpLua, LuaTable* lpTable, const char* name, Method lpMethod);
			/*
			//	Callback for Lua
			*/
			static int	callback(lua_State* lpLuaState);
			/*
			//	Call the Method
			*/
			int	call() const;

		private:
			Method	m_lpMethod;
		};








		/*
		//	Used for binding
		//	a const method to Lua
		//	0 Arguments
		//	Used internally
		*/
		template<typename Class, typename R>
		class ConstLuaMethod_0 : public LuaObject
		{
		public:
			typedef R (Class::*Method)() const;
			typedef ConstLuaMethod_0<Class,R>	Type;

			ConstLuaMethod_0(Lua* lpLua, Method lpMethod) : LuaObject(lpLua) , m_lpMethod(lpMethod) {}
			~ConstLuaMethod_0() {}

			/*
			//	Used to actually bind
			//	the Method to Lua
			*/
			static void bind(Lua* lpLua, LuaTable* lpTable, const char* name, Method lpMethod);
			/*
			//	Callback for Lua
			*/
			static int	callback(lua_State* lpLuaState);
			/*
			//	Call the Method
			*/
			int	call() const;

		private:
			Method	m_lpMethod;
		};



		/*
		//	Used for binding
		//	a const method to Lua
		//	1 Arguments
		//	Used internally
		*/
		template<typename Class, typename R, typename P0>
		class ConstLuaMethod_1 : public LuaObject
		{
		public:
			typedef R (Class::*Method)(P0) const;
			typedef ConstLuaMethod_1<Class,R,P0>	Type;

			ConstLuaMethod_1(Lua* lpLua, Method lpMethod) : LuaObject(lpLua) , m_lpMethod(lpMethod) {}
			~ConstLuaMethod_1() {}

			/*
			//	Used to actually bind
			//	the Method to Lua
			*/
			static void bind(Lua* lpLua, LuaTable* lpTable, const char* name, Method lpMethod);
			/*
			//	Callback for Lua
			*/
			static int	callback(lua_State* lpLuaState);
			/*
			//	Call the Method
			*/
			int	call() const;

		private:
			Method	m_lpMethod;
		};



		/*
		//	Used for binding
		//	a const method to Lua
		//	2 Arguments
		//	Used internally
		*/
		template<typename Class, typename R, typename P0, typename P1>
		class ConstLuaMethod_2 : public LuaObject
		{
		public:
			typedef R (Class::*Method)(P0,P1) const;
			typedef ConstLuaMethod_2<Class,R,P0,P1>	Type;

			ConstLuaMethod_2(Lua* lpLua, Method lpMethod) : LuaObject(lpLua) , m_lpMethod(lpMethod) {}
			~ConstLuaMethod_2() {}

			/*
			//	Used to actually bind
			//	the Method to Lua
			*/
			static void bind(Lua* lpLua, LuaTable* lpTable, const char* name, Method lpMethod);
			/*
			//	Callback for Lua
			*/
			static int	callback(lua_State* lpLuaState);
			/*
			//	Call the Method
			*/
			int	call() const;

		private:
			Method	m_lpMethod;
		};
		


		/*
		//	Used for binding
		//	a const method to Lua
		//	3 Arguments
		//	Used internally
		*/
		template<typename Class, typename R, typename P0, typename P1, typename P2>
		class ConstLuaMethod_3 : public LuaObject
		{
		public:
			typedef R (Class::*Method)(P0,P1,P2) const;
			typedef ConstLuaMethod_3<Class,R,P0,P1,P2>	Type;

			ConstLuaMethod_3(Lua* lpLua, Method lpMethod) : LuaObject(lpLua) , m_lpMethod(lpMethod) {}
			~ConstLuaMethod_3() {}

			/*
			//	Used to actually bind
			//	the Method to Lua
			*/
			static void bind(Lua* lpLua, LuaTable* lpTable, const char* name, Method lpMethod);
			/*
			//	Callback for Lua
			*/
			static int	callback(lua_State* lpLuaState);
			/*
			//	Call the Method
			*/
			int	call() const;

		private:
			Method	m_lpMethod;
		};



		/*
		//	Used for binding
		//	a const method to Lua
		//	4 Arguments
		//	Used internally
		*/
		template<typename Class, typename R, typename P0, typename P1, typename P2, typename P3>
		class ConstLuaMethod_4 : public LuaObject
		{
		public:
			typedef R (Class::*Method)(P0,P1,P2,P3) const;
			typedef ConstLuaMethod_4<Class,R,P0,P1,P2,P3>	Type;

			ConstLuaMethod_4(Lua* lpLua, Method lpMethod) : LuaObject(lpLua) , m_lpMethod(lpMethod) {}
			~ConstLuaMethod_4() {}

			/*
			//	Used to actually bind
			//	the Method to Lua
			*/
			static void bind(Lua* lpLua, LuaTable* lpTable, const char* name, Method lpMethod);
			/*
			//	Callback for Lua
			*/
			static int	callback(lua_State* lpLuaState);
			/*
			//	Call the Method
			*/
			int	call() const;

		private:
			Method	m_lpMethod;
		};



		/*
		//	Used for binding
		//	a const method to Lua
		//	5 Arguments
		//	Used internally
		*/
		template<typename Class, typename R, typename P0, typename P1, typename P2, typename P3, typename P4>
		class ConstLuaMethod_5 : public LuaObject
		{
		public:
			typedef R (Class::*Method)(P0,P1,P2,P3,P4) const;
			typedef ConstLuaMethod_5<Class,R,P0,P1,P2,P3,P4>	Type;

			ConstLuaMethod_5(Lua* lpLua, Method lpMethod) : LuaObject(lpLua) , m_lpMethod(lpMethod) {}
			~ConstLuaMethod_5() {}

			/*
			//	Used to actually bind
			//	the Method to Lua
			*/
			static void bind(Lua* lpLua, LuaTable* lpTable, const char* name, Method lpMethod);
			/*
			//	Callback for Lua
			*/
			static int	callback(lua_State* lpLuaState);
			/*
			//	Call the Method
			*/
			int	call() const;

		private:
			Method	m_lpMethod;
		};



		/*
		//	Used for binding
		//	a const method to Lua
		//	6 Arguments
		//	Used internally
		*/
		template<typename Class, typename R, typename P0, typename P1, typename P2, typename P3, typename P4, typename P5>
		class ConstLuaMethod_6 : public LuaObject
		{
		public:
			typedef R (Class::*Method)(P0,P1,P2,P3,P4,P5) const;
			typedef ConstLuaMethod_6<Class,R,P0,P1,P2,P3,P4,P5>	Type;

			ConstLuaMethod_6(Lua* lpLua, Method lpMethod) : LuaObject(lpLua) , m_lpMethod(lpMethod) {}
			~ConstLuaMethod_6() {}

			/*
			//	Used to actually bind
			//	the Method to Lua
			*/
			static void bind(Lua* lpLua, LuaTable* lpTable, const char* name, Method lpMethod);
			/*
			//	Callback for Lua
			*/
			static int	callback(lua_State* lpLuaState);
			/*
			//	Call the Method
			*/
			int	call() const;

		private:
			Method	m_lpMethod;
		};



		/*
		//	Used for binding
		//	a const method to Lua
		//	7 Arguments
		//	Used internally
		*/
		template<typename Class, typename R, typename P0, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6>
		class ConstLuaMethod_7 : public LuaObject
		{
		public:
			typedef R (Class::*Method)(P0,P1,P2,P3,P4,P5,P6) const;
			typedef ConstLuaMethod_7<Class,R,P0,P1,P2,P3,P4,P5,P6>	Type;

			ConstLuaMethod_7(Lua* lpLua, Method lpMethod) : LuaObject(lpLua) , m_lpMethod(lpMethod) {}
			~ConstLuaMethod_7() {}

			/*
			//	Used to actually bind
			//	the Method to Lua
			*/
			static void bind(Lua* lpLua, LuaTable* lpTable, const char* name, Method lpMethod);
			/*
			//	Callback for Lua
			*/
			static int	callback(lua_State* lpLuaState);
			/*
			//	Call the Method
			*/
			int	call() const;

		private:
			Method	m_lpMethod;
		};

	}

}

#include "LuaMethod.inl"
#endif